﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MuseLibrary
{
    public static class Extensions
    {
        public static int DropLeadingBits(this int value, int bitCount)
        {
            for (int i = 7; i > 7 - bitCount; i--)
            {
                value = value % (1 << i);
            }

            return value;
        }

        public static bool IsValidNibble(this int value)
        {
            return value == 0xf || value == 0xe || value == 0xd || value == 0xc || value == 0xb || value == 0xa || value == 0x9;
        }

        public static List<int> ReversedSubset(this List<int> data, int startIndex, int? count = null)
        {
            var output = new List<int>();
            var endIndex = (count.HasValue) ? startIndex + count.Value : data.Count;
            for (int i = endIndex - 1; i >= startIndex; i--)
            {
                output.Add(data[i]);
            }

            return output;
        }

        public static List<int> To10BitIntegers(this List<int> values, int startIndex, int count)
        {
            var output = new List<int>();

            for (int i = 0; i < count; i++)
            {
                var value = values[startIndex + i] >> (i * 2);
                var bitShift = (1 << ((i + 1) * 2)) - 1;
                var add = values[startIndex + i + 1] & bitShift;
                var newValue = value + (add << (8 - (i * 2)));
                output.Add(newValue);
            }

            return output;
        }

        public static int To16BitInteger(this List<int> data, int startIndex)
        {
            return (data[startIndex] << 8) + data[startIndex + 1];
        }

        public static int To32BitInteger(this List<int> data, int startIndex)
        {
            return (data[startIndex] << 24) + (data[startIndex + 1] << 16) + (data[startIndex + 2] << 8) + data[startIndex + 3];
        }

        public static int ToElias(this List<bool> bits, int eliasLength)
        {
            var output = 0;
            var currentBitShift = eliasLength;
            for (int i = eliasLength; i < bits.Count; i++)
            {
                if (bits[i]) output += 1 << currentBitShift;
                currentBitShift--;
            }

            return output;
        }

        public static int ToInteger(this List<bool> bits)
        {
            var output = 0;
            for (int i = 0; i < bits.Count; i++)
            {
                if (bits[i])
                    output += 1 << bits.Count - i - 1;
            }

            return output;
        }

        public static bool[] ToBitArray(this List<int> values)
        {
            var output = new bool[values.Count * 8];
            var counter = 0;
            for (int i = 0; i < values.Count; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    var bitShift = 1 << (7 - j);
                    output[counter++] = (values[i] & bitShift) == bitShift;
                }
            }

            return output;
        }

        public static List<int> Subset(this List<int> data, int startIndex, int? count = null)
        {
            var output = new List<int>();
            var endIndex = (count.HasValue) ? startIndex + count.Value : data.Count;
            for (int i = startIndex; i < endIndex; i++)
            {
                output.Add(data[i]);
            }

            return output;
        }
    }
}
